const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const QRCode = require('qrcode');
const AppInfoParser = require('app-info-parser');
const crypto = require('crypto');
const { Files } = require('./db');
const Sequelize = require('sequelize');

const app = express();
const port = 8001;

// 配置文件存储
const uploadDir = path.join(__dirname, 'uploads');
if (!fs.existsSync(uploadDir)) {
    fs.mkdirSync(uploadDir);
}

const tempDir = path.join(uploadDir, 'temp');
if (!fs.existsSync(tempDir)) {
    fs.mkdirSync(tempDir, { recursive: true });
}

const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        // 生成唯一临时目录
        const uniqueStr = crypto.randomBytes(16).toString('hex');
        const tempUploadDir = path.join(tempDir, uniqueStr);
        fs.mkdirSync(tempUploadDir, { recursive: true });
        req.tempUploadDir = tempUploadDir;
        cb(null, tempUploadDir);
    },
    filename: function (req, file, cb) {
        const decodedFilename = Buffer.from(file.originalname, 'latin1').toString('utf8');
        cb(null, decodedFilename);
    }
});

const upload = multer({ storage: storage });

// 配置静态文件服务
app.use('/uploads', express.static(uploadDir));
app.use(express.static(path.join(__dirname, 'html')));



// 处理文件上传
app.post('/upload', upload.single('file'), async (req, res) => {
    if (!req.file) {
        return res.status(400).json({
            code: -1,
            message: '没有文件被上传'
        });
    }

    try {
        const protocol = req.protocol;
        const host = req.get('host');
        const baseUrl = `${protocol}://${host}`;

        let apkInfo = {
            buildVersion: '',
            buildVersionNo: '',
            appName: '',
            packageName: '',
            iconUrl: ''
        };
        let tempUploadDir = req.tempUploadDir || path.dirname(req.file.path);
        let targetDir = tempUploadDir;
        let finalFilePath = req.file.path;
        let relativePath = '';
        let relativeQrPath = '';
        let qrPath = '';
        let downloadUrl = '';
        let parsedInfo = null;
        let needRemoveTemp = false;
        // 仅apk/ipa需解析包名
        if (req.file.originalname.toLowerCase().endsWith('.apk') || req.file.originalname.toLowerCase().endsWith('.ipa')) {
            parsedInfo = await genProfile(req.file.path, apkInfo, baseUrl, uploadDir);
            if (parsedInfo && parsedInfo.packageName) {
                apkInfo = parsedInfo;
                // 重新生成目标目录，调整为 uploads/包名/版本号/日期/文件名
                const today = new Date();
                const dateStr = today.getFullYear().toString() +
                    (today.getMonth() + 1).toString().padStart(2, '0') +
                    today.getDate().toString().padStart(2, '0');
                const versionStr = apkInfo.buildVersion || 'unknown';
                const packageName = apkInfo.packageName || 'unknown';
                const newTargetDir = path.join(uploadDir, packageName, versionStr, dateStr);
                fs.mkdirSync(newTargetDir, { recursive: true });
                // 移动文件
                const newFilePath = path.join(newTargetDir, path.basename(req.file.path));
                // 移动文件前判断目标文件是否存在，存在则先删除
                if (fs.existsSync(newFilePath)) {
                    fs.unlinkSync(newFilePath);
                }
                fs.renameSync(req.file.path, newFilePath);
                // 移动icon和profile
                const oldIcon = req.file.path + '_icon.png';
                const oldProfile = req.file.path + '_profile.json';
                const newIcon = newFilePath + '_icon.png';
                const newProfile = newFilePath + '_profile.json';
                if (fs.existsSync(oldIcon)) fs.renameSync(oldIcon, newIcon);
                if (fs.existsSync(oldProfile)) fs.renameSync(oldProfile, newProfile);
                finalFilePath = newFilePath;
                targetDir = newTargetDir;
                needRemoveTemp = true;
            }
        } else {
            // 非apk/ipa直接移动到uploads/other/yyyyMMdd
            const today = new Date();
            const dateStr = today.getFullYear().toString() +
                (today.getMonth() + 1).toString().padStart(2, '0') +
                today.getDate().toString().padStart(2, '0');
            const newTargetDir = path.join(uploadDir, 'other', dateStr);
            fs.mkdirSync(newTargetDir, { recursive: true });
            const newFilePath = path.join(newTargetDir, path.basename(req.file.path));
            // 移动文件前判断目标文件是否存在，存在则先删除
            if (fs.existsSync(newFilePath)) {
                fs.unlinkSync(newFilePath);
            }
            fs.renameSync(req.file.path, newFilePath);
            finalFilePath = newFilePath;
            targetDir = newTargetDir;
            needRemoveTemp = true;
        }
        relativePath = path.relative(uploadDir, finalFilePath);
        downloadUrl = `${baseUrl}/download?file=${encodeURIComponent(relativePath)}`;
        const qrCodeDataURL = await QRCode.toDataURL(downloadUrl);

        // 删除临时目录
        if (req.tempUploadDir && needRemoveTemp) {
            fs.rmSync(req.tempUploadDir, { recursive: true, force: true });
        }

        // 使用Sequelize模型写入数据库
        await Files.create({
            name: path.basename(finalFilePath),
            path: relativePath,
            size: fs.statSync(finalFilePath).size,
            buildVersion: apkInfo.buildVersion,
            buildVersionNo: apkInfo.buildVersionNo,
            buildUpdated: new Date().toLocaleString(),
            buildQRCodeURL: qrCodeDataURL,
            buildShortcutUrl: `${baseUrl}/download?file=${encodeURIComponent(relativePath)}`,
            packageName: apkInfo.packageName,
            appName: JSON.stringify(apkInfo.appName),
            iconUrl: apkInfo.iconUrl,
            apkInfo: JSON.stringify(apkInfo),
            createdAt: new Date().toISOString()
        });
        res.json({
            code: 0,
            data: {
                buildVersion: apkInfo.buildVersion,
                buildVersionNo: apkInfo.buildVersionNo,
                buildUpdated: new Date().toLocaleString(),
                buildQRCodeURL: qrCodeDataURL,
                buildShortcutUrl: `${baseUrl}/download?file=${encodeURIComponent(relativePath)}`,
                packageName: apkInfo.packageName,
                appName: apkInfo.appName,
                iconUrl: apkInfo.iconUrl
            }
        });
    } catch (e) {
        console.error('文件上传失败:', e);
        // 返回错误信息
        res.status(500).json({
            code: -1,
            message: '文件上传失败',
            error: e.message
        });
        // 删除临时目录
        if (req.tempUploadDir) {
            fs.rmSync(req.tempUploadDir, { recursive: true, force: true });
        }
    }
});

// 修改文件列表API为从数据库查询
app.get('/api/files', async (req, res) => {
    try {
        // 获取分页参数
        let page = parseInt(req.query.page, 10) || 1;
        let pageSize = parseInt(req.query.pageSize, 10) || 30;
        if (page < 1) page = 1;
        if (pageSize < 1) pageSize = 30;
        
        // 构建查询条件
        const where = {};
        if (req.query.search) {
            where[Sequelize.Op.or] = [
                { packageName: { [Sequelize.Op.like]: `%${req.query.search}%` } },
                { appName: { [Sequelize.Op.like]: `%${req.query.search}%` } }
            ];
        }
        
        // 从数据库查询文件列表
        const { count, rows } = await Files.findAndCountAll({
            where,
            offset: (page - 1) * pageSize,
            limit: pageSize,
            order: [['createdAt', 'DESC']]
        });
        
        const protocol = req.protocol;
        const host = req.get('host');
        const baseUrl = `${protocol}://${host}`;
        
        // 格式化返回数据
        const fileList = rows.map(file => ({
            name: file.name,
            isDirectory: false,
            path: file.path,
            size: file.size,
            buildUpdated: file.buildUpdated,
            iconUrl: file.iconUrl,
            buildQRCodeURL: file.buildQRCodeURL,
            buildShortcutUrl: file.buildShortcutUrl,
            packageName: file.packageName,
            appName: JSON.parse(file.appName),
            buildVersion: file.buildVersion,
            buildVersionNo: file.buildVersionNo
        }));
        
        res.json({
            total: count,
            page,
            pageSize,
            cursor: '',
            list: fileList
        });
    } catch (err) {
        console.error('查询文件列表失败:', err);
        res.status(500).json({ error: '查询文件列表失败' });
    }
});

// 修改文件下载路由
app.get('/download', (req, res) => {
    const filename = req.query.file;
    if (!filename) {
        return res.status(400).send('文件名不能为空');
    }

    // 验证Referer头，防止盗链
    const referer = req.headers.referer;
    const host = req.get('host');
    if (!referer || !referer.includes(host)) {
        return res.status(403).send('请从官网点击下载');
    }

    const filepath = path.join(uploadDir, filename);

    // 验证文件路径，确保不会访问上级目录
    const realPath = path.resolve(filepath);
    if (!realPath.startsWith(path.resolve(uploadDir))) {
        return res.status(403).send('非法的文件路径');
    }

    if (!fs.existsSync(filepath)) {
        return res.status(404).send('文件不存在');
    }

    res.download(filepath);
});


// 新增最近上传文件接口
app.get('/api/recent-files', async (req, res) => {
    try {
        let count = parseInt(req.query.count, 10) || 10;
        if (count < 1) count = 10;
        const protocol = req.protocol;
        const host = req.get('host');
        const baseUrl = `${protocol}://${host}`;
        
        const fileList = await Files.findAll({
            limit: count,
            order: [['createdAt', 'DESC']]
        });
        
        res.json({
            count: fileList.length,
            list: fileList.map(file => {
                file.appName = JSON.parse(file.appName);
                return file;
            })
        });
    } catch (err) {
        console.error('获取最近文件列表失败:', err);
        res.status(500).json({ error: '获取最近文件列表失败' });
    }
});

// 启动服务器
app.listen(port, () => {
    console.log(`服务器运行在 http://localhost:${port}`);
    console.log(`上传目录: ${uploadDir}`);
    console.log(`临时目录: ${tempDir}`);
});

// 解析 APK 文件信息
async function parseApkInfo(filePath) {
    try {
        const parser = new AppInfoParser(filePath);
        const result = await parser.parse();

        const isIOS = filePath.endsWith('.ipa');

        const apkInfo = Object.assign({}, result, {
            buildVersion: isIOS ? result.CFBundleShortVersionString : result.versionName,
            buildVersionNo: isIOS ? result.CFBundleVersion : result.versionCode.toString(),
            appName: isIOS ? result.CFBundleName : result.application.label,
            packageName: isIOS ? result.CFBundleIdentifier : result.package,
            icon: result.icon
        });
        return apkInfo;
    } catch (error) {
        console.error('解析 APK 文件失败:', error);
        return null;
    }
}
async function genProfile(reqPath, apkInfo, baseUrl, uploadDir) {
    const parsedInfo = await parseApkInfo(reqPath);
    if (parsedInfo) {
        apkInfo = parsedInfo;

        // 直接返回base64格式的图标数据
        if (parsedInfo.icon) {
            apkInfo.iconUrl = parsedInfo.icon;
        }
    }
    return apkInfo;
}